/*
	Contains headers for the Win32 window encapsulation class 'Window'

	Author: Aidan Goddard 9/3/14
*/

#ifndef WINDOW_H_INCLUDED
#define WINDOW_H_INCLUDED

#define WIN32_LEAN_AND_MEAN
#include<Windows.h>

#include<map>
#include<set>
#include<stdint.h>
#pragma comment(lib, "libwindow64.lib")

#define INIT_SUCCESS 0
#define INIT_MODE_NOT_RECOGNISED -1
#define INIT_CLASS_REGISTRATION_FAIL -2

namespace Snowstorm
{
	/////////////////////////////////////////////////////////////
	// some enums
	enum w_mode_t {MODE_SINGLE, MODE_MULTIPLE};
	enum w_type_t {TYPE_POPUP, TYPE_NO_BOARDER, TYPE_FULLSCREEN, TYPE_EXCLUSIVE_FULLSCREEN};

	/////////////////////////////////////////////////////////////
	// the window_type structure
	struct WindowAttributes
	{
		HWND		parent_hwnd;
		LPCWSTR		title;
		int			x;
		int			y;
		int			width;
		int			height;
		bool		catch_input;
		w_type_t	window_type;
	};

	/////////////////////////////////////////////////////////////
	// the Window class
	class Window
	{
		// static data
	private:
		static std::set<HWND> hwnd_list;
		static std::map <HWND, Window*> hwnd_map;
		static Window *swi;
		static w_mode_t mode;

		// data
	private:
		uint32_t KEYSTATES[8];
		int mouse_abs_x, mouse_abs_y;
		HWND hwnd;
		HWND parent;
		DWORD style;
		std::map <UINT, void(*)(Window*, WPARAM, LPARAM)> msg_handlers;
		void(*key_pressed_event)(Window*, uint8_t);
		void(*key_released_event)(Window*, uint8_t);
		void(*mouse_event)(Window*, int, int, short);

		// static functions
	public:
		static int Initialise(w_mode_t mode);
		static void Finish();
		static Window* Create(WindowAttributes *window_attributes);
		static int MessageLoop();

	private:
		static LRESULT CALLBACK MsgRouter(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
		static LRESULT CALLBACK SingleWindowRouter(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
		static void Remove(Window *wnd);

		// instance functions
	public:
		DWORD GetWindowStyle();
		void RegisterKeyPressedEventHandler(void(*key_pressed_event_handler)(Window*, uint8_t));
		void RegisterKeyReleasedEventHandler(void(*key_released_event_handler)(Window*, uint8_t));
		void RegisterMouseEventHandler(void(*mouse_event_handler)(Window*, int, int, short));
		void Resize(int x, int y, int width, int height);
		void Resize(int width, int height);
		void Show();
		void Hide();
		void Kill();
		void Minimize();
		void Maximize();
		HWND GetHWND();
		void RegisterHandler(UINT handle, void(*handler)(Window *wnd, WPARAM, LPARAM));

	private:
		void HandleUserInput(WPARAM wparam, LPARAM lparam);
		LRESULT CALLBACK InstanceMsgHandler(UINT msg, WPARAM wparam, LPARAM lparam);
		Window(HWND hwnd);
		~Window();

	};
};


#endif
